package com.gpnu7_412.yanzhi.controller.user;

import com.gpnu7_412.yanzhi.entity.User;
import com.gpnu7_412.yanzhi.exception.custom.DataInconsistencyException;
import com.gpnu7_412.yanzhi.exception.custom.RequestDataException;
import com.gpnu7_412.yanzhi.service.UserService;
import com.gpnu7_412.yanzhi.util.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 用户登录控制器
 * @author ZZH
 */
@CrossOrigin
@RestController
@RequestMapping("/user/login")
public class LoginController {

    @Autowired
    private UserService userService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 用户使用密码登录
     * @param requestMap 请求数据，需包含：email 用户邮箱，password 用户密码
     * @return 响应对象
     */
    @PostMapping("/password")
    public Result loginByPassword(@RequestBody Map<String, Object> requestMap) {
        // 获取数据
        String email = (String) requestMap.get("email");
        String password = (String) requestMap.get("password");
        // 查询待登录的用户
        User user = userService.loginByPassword(email, password);
        if (user == null) {
            throw new RequestDataException("参数为空");
        }
        // 获取 jwt 令牌
        String jwtToken = userService.getJwtToken(user);
        // 把 jwt 令牌存入 Redis
        ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
        operations.set(jwtToken, jwtToken, 6, TimeUnit.HOURS);
        Map<String, Object> responseMap = new HashMap<>(2);
        responseMap.put("jwtToken", jwtToken);
        responseMap.put("userId", user.getUserId());
        responseMap.put("permission", user.getPermission());
        return new Result(responseMap);
    }

    /**
     * 用户使用验证码登录
     * @param requestMap 请求数据，需包含：email 用户邮箱，verification：邮箱验证码
     * @return 响应对象
     */
    @PostMapping("/verification")
    public Result loginByVerification(@RequestBody Map<String, Object> requestMap) {
        // 获取信息
        String email = (String) requestMap.get("email");
        String verification = (String) requestMap.get("verification");
        // 尝试从 Redis 中取出验证码
        ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
        String storeCode = operations.get(email);
        // 验证码校验
        if (storeCode == null || !storeCode.equals(verification)) {
            throw new DataInconsistencyException("验证码错误");
        }
        User user = userService.loginByVerification(email);
        if (user == null) {
            throw new RequestDataException("参数为空");
        }
        // 获取 jwt 令牌
        String jwtToken = userService.getJwtToken(user);
        // 把 jwt 令牌存入 Redis
        operations.set(jwtToken, jwtToken, 6, TimeUnit.HOURS);
        Map<String, Object> responseMap = new HashMap<>(2);
        responseMap.put("jwtToken", jwtToken);
        responseMap.put("userId", user.getUserId());
        responseMap.put("permission", user.getPermission());
        return new Result(responseMap);
    }

    /**
     * 用户忘记密码
     * @param requestMap 请求数据，需包含：email 用户邮箱，verification：邮箱验证码，newPassword：新密码
     * @return 响应数据
     */
    @PutMapping("/forget")
    public Result forgetPassword(@RequestBody Map<String, Object> requestMap) {
        // 获取信息
        String email = (String) requestMap.get("email");
        String verification = (String) requestMap.get("verification");
        String newPassword = (String) requestMap.get("newPassword");
        // 尝试从 Redis 中取出验证码
        ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
        String storeCode = operations.get(email);
        // 验证码校验
        if (storeCode == null || !storeCode.equals(verification)) {
            throw new DataInconsistencyException("验证码错误");
        }
        if (!userService.forgetPassword(email, newPassword)) {
            throw new RequestDataException("参数为空");
        }
        return new Result();
    }
}
